﻿using SD.Common;
using SD.Infrastructure.EntityBase;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlamDunk.ValueObjects.Enums;
using SlamDunk.ValueObjects.Interfaces;

namespace SlamDunk.MES.Domain.Entities.DefinitionContext
{
    /// <summary>
    /// 物料清单
    /// </summary>
    public class Bom : AggregateRootEntity, ICheckable, IDisable
    {
        #region # 构造器

        #region 00.无参构造器
        /// <summary>
        /// 无参构造器
        /// </summary>
        protected Bom()
        {
            //初始化导航属性
            this.Items = new HashSet<BomItem>();

            //默认值
            this.CheckStatus = CheckStatus.Unchecked;
            this.Enabled = false;
        }
        #endregion

        #region 01.创建物料清单构造器
        /// <summary>
        /// 创建物料清单构造器
        /// </summary>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public Bom(string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description)
            : this()
        {
            base.Number = bomNo;
            base.Name = bomName;
            this.VersionNo = versionNo;
            this.ProductId = productId;
            this.RunSize = runSize;
            this.EffectedDate = effectedDate?.Date;
            this.ExpiredDate = expiredDate?.Date;
            this.FacilityId = facilityId;
            this.Description = description;

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #endregion

        #region # 属性

        #region 版本号 —— string VersionNo
        /// <summary>
        /// 版本号
        /// </summary>
        public string VersionNo { get; private set; }
        #endregion

        #region 产品Id —— Guid ProductId
        /// <summary>
        /// 产品Id
        /// </summary>
        public Guid ProductId { get; private set; }
        #endregion

        #region 运行规模 —— decimal RunSize
        /// <summary>
        /// 运行规模
        /// </summary>
        public decimal RunSize { get; private set; }
        #endregion

        #region 生效日期 —— DateTime? EffectedDate
        /// <summary>
        /// 生效日期
        /// </summary>
        public DateTime? EffectedDate { get; private set; }
        #endregion

        #region 失效日期 —— DateTime? ExpiredDate
        /// <summary>
        /// 失效日期
        /// </summary>
        public DateTime? ExpiredDate { get; private set; }
        #endregion

        #region 工厂模型Id —— Guid? FacilityId 
        /// <summary>
        /// 工厂模型Id
        /// </summary>
        public Guid? FacilityId { get; private set; }
        #endregion

        #region 是否启用 —— bool Enabled
        /// <summary>
        /// 是否启用
        /// </summary>
        public bool Enabled { get; set; }
        #endregion

        #region 启用人账号 —— string EnablerAccount
        /// <summary>
        /// 启用人账号
        /// </summary>
        public string EnablerAccount { get; set; }
        #endregion

        #region 启用人姓名 —— string EnablerName
        /// <summary>
        /// 启用人姓名
        /// </summary>
        public string EnablerName { get; set; }
        #endregion

        #region 停用人账号 —— string DisablerAccount
        /// <summary>
        /// 停用人账号
        /// </summary>
        public string DisablerAccount { get; set; }
        #endregion

        #region 停用人姓名 —— string DisablerName
        /// <summary>
        /// 停用人姓名
        /// </summary>
        public string DisablerName { get; set; }
        #endregion

        #region 停用原因 —— string DisabledReason
        /// <summary>
        /// 停用原因
        /// </summary>
        public string DisabledReason { get; set; }
        #endregion

        #region 提审人账号 —— string SubmitterAccount
        /// <summary>
        /// 提审人账号
        /// </summary>
        public string SubmitterAccount { get; set; }
        #endregion

        #region 提审人姓名 —— string SubmitterName
        /// <summary>
        /// 提审人姓名
        /// </summary>
        public string SubmitterName { get; set; }
        #endregion

        #region 审核状态 —— CheckStatus CheckStatus
        /// <summary>
        /// 审核状态
        /// </summary>
        public CheckStatus CheckStatus { get; set; }
        #endregion

        #region 审核意见 —— string CheckedRemark
        /// <summary>
        /// 审核意见
        /// </summary>
        public string CheckedRemark { get; set; }
        #endregion

        #region 审核人账号 —— string CheckerAccount
        /// <summary>
        /// 审核人账号
        /// </summary>
        public string CheckerAccount { get; set; }
        #endregion

        #region 审核人姓名 —— string CheckerName
        /// <summary>
        /// 审核人姓名
        /// </summary>
        public string CheckerName { get; set; }
        #endregion

        #region 审核时间 —— DateTime? CheckedTime
        /// <summary>
        /// 审核时间
        /// </summary>
        public DateTime? CheckedTime { get; set; }
        #endregion

        #region 描述 —— string Description
        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; private set; }
        #endregion

        #region 导航属性 - 物料清单项集 —— ICollection<BomItem> Items
        /// <summary>
        /// 导航属性 - 物料清单项集
        /// </summary>
        public virtual ICollection<BomItem> Items { get; private set; }
        #endregion

        #endregion

        #region # 方法

        #region 修改物料清单 —— void UpdateInfo(string bomNo, string bomName...
        /// <summary>
        /// 修改物料清单
        /// </summary>
        /// <param name="bomNo">物料清单编号</param>
        /// <param name="bomName">物料清单名称</param>
        /// <param name="versionNo">版本号</param>
        /// <param name="productId">产品Id</param>
        /// <param name="runSize">运行规模</param>
        /// <param name="effectedDate">生效日期</param>
        /// <param name="expiredDate">失效日期</param>
        /// <param name="facilityId">工厂模型Id</param>
        /// <param name="description">描述</param>
        public void UpdateInfo(string bomNo, string bomName, string versionNo, Guid productId, decimal runSize, DateTime? effectedDate, DateTime? expiredDate, Guid? facilityId, string description)
        {
            #region # 验证

            if (this.CheckStatus == CheckStatus.Checking)
            {
                throw new InvalidOperationException("审核中的物料清单不可修改！");
            }
            if (this.CheckStatus == CheckStatus.Passed)
            {
                throw new InvalidOperationException("审核通过的物料清单不可修改！");
            }

            #endregion

            base.Number = bomNo;
            base.Name = bomName;
            this.VersionNo = versionNo;
            this.ProductId = productId;
            this.RunSize = runSize;
            this.EffectedDate = effectedDate?.Date;
            this.ExpiredDate = expiredDate?.Date;
            this.FacilityId = facilityId;
            this.Description = description;

            //初始化关键字
            this.InitKeywords();
        }
        #endregion

        #region 设置物料清单项 —— void SetBomItems(IEnumerable<BomItem> bomItems)
        /// <summary>
        /// 追加物料清单项
        /// </summary>
        /// <param name="bomItems">物料清单项集</param>
        public void SetBomItems(IEnumerable<BomItem> bomItems)
        {
            bomItems = bomItems?.ToArray() ?? new BomItem[0];

            this.ClearItems();
            if (bomItems.Any())
            {
                this.Items.AddRange(bomItems);
                foreach (BomItem bomItem in bomItems)
                {
                    bomItem.Bom = this;
                }
            }
        }
        #endregion

        #region 提交审核 —— void Submit(string submitterAccount...
        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="submitterAccount">提审人账号</param>
        /// <param name="submitterName">提审人姓名</param>
        public void Submit(string submitterAccount, string submitterName)
        {
            this.DoSubmit(submitterAccount, submitterName);
        }
        #endregion

        #region 审核 —— void Check(bool passed, string checkedRemark...
        /// <summary>
        /// 审核
        /// </summary>
        /// <param name="passed">是否通过</param>
        /// <param name="checkedRemark">审核意见</param>
        /// <param name="checkedAccount">审核人账号</param>
        /// <param name="checkedName">审核人姓名</param>
        public void Check(bool passed, string checkedRemark, string checkedAccount, string checkedName)
        {
            this.DoCheck(passed, checkedRemark, checkedAccount, checkedName);
        }
        #endregion

        #region 启用 —— void Enable(string enablerAccount...
        /// <summary>
        /// 启用
        /// </summary>
        /// <param name="enablerAccount">启用人账号</param>
        /// <param name="enablerName">启用人姓名</param>
        public void Enable(string enablerAccount, string enablerName)
        {
            #region # 验证

            if (this.CheckStatus != CheckStatus.Passed)
            {
                throw new InvalidOperationException("未审核通过的物料清单不可启用！");
            }

            #endregion

            this.DoEnable(enablerAccount, enablerName);
        }
        #endregion

        #region 停用 —— void Disable(string diablerAccount...
        /// <summary>
        /// 停用
        /// </summary>
        /// <param name="diablerAccount">停用人账号</param>
        /// <param name="diablerName">停用人姓名</param>
        /// <param name="reason">停用原因</param>
        public void Disable(string diablerAccount, string diablerName, string reason)
        {
            this.DoDisable(diablerAccount, diablerName, reason);
        }
        #endregion

        #region 清空物料清单项 —— void ClearItems()
        /// <summary>
        /// 清空物料清单项
        /// </summary>
        private void ClearItems()
        {
            foreach (BomItem bomItem in this.Items.ToArray())
            {
                this.Items.Remove(bomItem);
            }
        }
        #endregion

        #region 初始化关键字 —— void InitKeywords()
        /// <summary>
        /// 初始化关键字
        /// </summary>
        private void InitKeywords()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(base.Number);
            builder.Append(base.Name);
            builder.Append(this.Description);

            base.SetKeywords(builder.ToString());
        }
        #endregion

        #endregion
    }
}
